home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Telnet 2.7b5 / source / network / netevent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-01  |  14.0 KB  |  522 lines  |  [TEXT/CWIE]

  1. /*
  2. *    netevent.c
  3. *     Originally by Gaige B. Paulsen
  4. *****************************************************************
  5. *    NCSA Telnet for the Macintosh                                *
  6. *                                                                *
  7. *    National Center for Supercomputing Applications                *
  8. *    Software Development Group                                    *
  9. *    152 Computing Applications Building                            *
  10. *    605 E. Springfield Ave.                                        *
  11. *    Champaign, IL  61820                                        *
  12. *                                                                *
  13. *    Copyright (c) 1986-1993,                                    *
  14. *    Board of Trustees of the University of Illinois                *
  15. *****************************************************************
  16. *    Network event handler for NCSA Telnet for the Macintosh
  17. *
  18. *    Called by:
  19. *        event.c
  20. *        maclook.c
  21. *
  22. *    Revisions:
  23. *    7/92    Telnet 2.6:  added the 2 global structures, and cleaned up defines -- Scott Bulmahn
  24. */
  25.  
  26. #ifdef MPW
  27. #pragma segment Network
  28. #endif
  29.  
  30.  
  31. #include "netevent.proto.h"
  32. #include "InternalEvents.h"
  33. #include "wind.h"
  34. #include "mydnr.proto.h"
  35. #include "bkgr.proto.h"
  36. #include "maclook.proto.h"
  37. #include "network.proto.h"
  38. #include "menuseg.proto.h"
  39. #include "rsinterf.proto.h"
  40. #include "vrrgmac.proto.h"
  41. #include "tekrgmac.proto.h"
  42. #include "vsdata.h"
  43. #include "vskeys.h"
  44. #include "translate.proto.h"
  45.  
  46. #include "parse.proto.h"
  47. #include "Connections.proto.h"
  48. #include "event.proto.h"
  49. #include "vsinterf.proto.h"
  50. #include "telneterrors.h"
  51.  
  52. extern WindRec
  53.     *screens;                    /* The screen array from Maclook */
  54. //extern char *tempspot;            /* 256 bytes for temp strings */
  55. extern short scrn;
  56.  
  57. short
  58.     FileInTransit,
  59.     gBlocksize[MaxSess],        /*    how large do we make the blocks when we read? */
  60.     gQueueError = 0,            //    Set to 1 if the queue fills up.
  61.     gQueueLength = 0,            //    Used to monitor queue length for debugging purposes.
  62.     gQueueInUse = 0;            //        Ditto.
  63.     
  64. QHdr    gEventsQueue, gEventsFreeQueue;
  65.         
  66. unsigned char *gReadspace = 0;        /* main buffer space */
  67.  
  68. #define PFTP 1
  69. #define PRCP 2
  70. #define PDATA 3
  71.  
  72. #ifdef __MWERKS__
  73. #pragma profile off
  74. #endif
  75.  
  76. //    Our "give time" routine
  77. void Stask( void)
  78. {
  79. }
  80.  
  81. //    Every time we open or close a network connection, we add or remove a few elements
  82. //    to/from the queue to assure that there will always be some free elements laying
  83. //    around.  This allows us to avoid Dequeue'ing at interrupt time, which causes 
  84. //    nasty mutex problems since we walk the queue in netgetevent at non-interrupt time.
  85. void    ChangeQueueLength(short delta)
  86. {
  87.     internal_event    *theEvent;
  88.     
  89.     if (delta > 0)
  90.         while (delta != 0) {
  91.             theEvent = (internal_event *) myNewPtrCritical(sizeof(internal_event));
  92.             Enqueue((QElemPtr)theEvent, &gEventsFreeQueue);
  93.             gQueueLength++;
  94.             delta--;
  95.             }
  96.     else
  97.         while (delta != 0) {
  98.             theEvent = (internal_event *)gEventsFreeQueue.qHead;
  99.             Dequeue((QElemPtr)theEvent, &gEventsFreeQueue);
  100.             if (theEvent) DisposePtr((Ptr)theEvent);
  101.             gQueueLength--;
  102.             delta++;
  103.             }
  104. }
  105.             
  106. /***********************************************************************/
  107. /*  netgetevent
  108. *   Retrieves the next event (and clears it) which matches bits in
  109. *   the given mask.  Returns the event number or -1 on no event present.
  110. *   Also returns the exact class and the associated integer in reference
  111. *   parameters.
  112. */
  113.  
  114. short netgetevent(
  115. //    short    mask,
  116.     short    *class,
  117.     short    *data1,
  118.     long    *data2
  119.   )
  120. {
  121.     internal_event    *theEvent;
  122.     short            event;
  123. //#define    QUEUE_STATS
  124. #ifdef    QUEUE_STATS
  125.     char            qs[255];
  126.     static    long    timer = 0;
  127.     
  128.     if (TickCount() - timer > 60*30) {
  129.         sprintf(qs, "QueueLength: %d, InUse: %d", gQueueLength, gQueueInUse);
  130.         timer = TickCount();
  131.         putln(qs);
  132.         }
  133. #endif    QUEUE_STATS
  134.  
  135.     if (gQueueError)                // Yikes, we actually ran out of queue elements!
  136.         DebugStr("\pOut of Queue Elements, please quit as quickly as possible!");
  137.         
  138.     // Spin until we hit the end of the queue or if we Dequeue an element that is not
  139.     // already dequeued.  If we don't do this check on Dequeue, someone else could come
  140.     // in and dequeue an element that we are about to dequeue.  Thus, WHAM! we both have
  141.     // that queue element.
  142.     while ((theEvent = (internal_event *)gEventsQueue.qHead) != NULL) {
  143.         if (Dequeue((QElemPtr)theEvent, &gEventsQueue) == noErr)
  144.             break;
  145.         }
  146.         
  147. //    while ((theEvent != NULL) && !(theEvent->eclass & mask))
  148. //        theEvent = (internal_event *)theEvent->qLink;
  149.     
  150.     if (theEvent == NULL) return(-1);
  151.         
  152. //    (void) Dequeue((QElemPtr)theEvent, &gEventsQueue);
  153.  
  154.     *class = theEvent->eclass;
  155.     *data1 = theEvent->data1;
  156.     *data2 = theEvent->data2;
  157.     event = theEvent->event;
  158.     
  159.     Enqueue((QElemPtr)theEvent, &gEventsFreeQueue);
  160.     gQueueInUse--;
  161.     return(event);
  162. }
  163.  
  164. /***********************************************************************/
  165. /*  netputevent
  166. *   add an event to the queue.
  167. *   Will probably get the memory for the entry from the free list.
  168. *   Returns 0 if there was room, 1 if an event was lost.
  169. */
  170. short netputevent(short theclass, short what, short data1, long data2)
  171. {
  172.     internal_event    *theEvent;
  173.     
  174.     while ((theEvent = (internal_event *)gEventsFreeQueue.qHead) != NULL) {
  175.         if (Dequeue((QElemPtr)theEvent, &gEventsFreeQueue) == noErr)
  176.             break;
  177.         }
  178.             
  179.     if (theEvent == NULL) {
  180.         gQueueError = 1;                    // Darn, we filled the queue, alert the user.
  181.         return(-1);
  182.         }
  183.     else
  184.         gQueueInUse++;
  185.         
  186.     theEvent->qType = 0;    
  187.     theEvent->eclass = theclass;
  188.     theEvent->event = what;
  189.     theEvent->data1 = data1;
  190.     theEvent->data2 = data2;
  191.     
  192.     Enqueue((QElemPtr)theEvent, &gEventsQueue);
  193.     return(0);
  194. }
  195.  
  196. /***************************************************************************/
  197. /*  netputuev
  198. *   put a unique event into the queue
  199. *   First searches the queue for like events
  200. */
  201. short netputuev(short tclass, short    what, short    data1, long    data2)
  202. {
  203.     internal_event    *theEvent = (internal_event *)gEventsQueue.qHead;
  204.     
  205.     while((theEvent != NULL) && ((theEvent->eclass != tclass) || (theEvent->event != what)
  206.             || (theEvent->data1 != data1) || (theEvent->data2 != data2)))
  207.                 theEvent = (internal_event *)theEvent->qLink;
  208.                 
  209.     if (theEvent != NULL) return(0);
  210.     
  211.     return(netputevent(tclass, what, data1, data2));
  212. }
  213.  
  214. void FlushNetwork(short scrn)
  215. {
  216.     short cnt;
  217.     
  218.     RSskip(screens[scrn].vs, 1);                /* Don't do any output */
  219.     cnt = gBlocksize[scrn];                        /* just needs to be positive to begin with */
  220.     
  221.     while (cnt>0) {
  222.         cnt = netread(screens[scrn].port,gReadspace,gBlocksize[scrn]);
  223.         parse( &screens[scrn ], gReadspace, cnt);
  224.         }
  225.  
  226.     RSskip(screens[scrn].vs, 0);                /* Do output now */
  227.     SetPort( screens[scrn].wind);
  228.     InvalRect(&screens[scrn].wind->portRect);    /* Don't forget to redraw */
  229. }
  230.  
  231. void pasteText(short scrn)
  232. {
  233.     short amount;
  234.     if (!screens[scrn].outlen)
  235.         return;
  236.  
  237.  
  238.     if (netpush(screens[scrn].port) != 0) {            /* BYU 2.4.16 - wait until not busy */
  239.         netputevent( USERCLASS, PASTELEFT, scrn,0);    /* BYU 2.4.16 */
  240.         return;                                        /* BYU 2.4.16 */
  241.     }                                                /* BYU 2.4.16 */
  242.     if (screens[scrn].incount) {                    /* BYU 2.4.16 */
  243.         screens[scrn].incount = 0;                    /* BYU 2.4.16 */
  244.         screens[scrn].outcount = 0;                    /* BYU 2.4.16 */
  245.         netputevent( USERCLASS, PASTELEFT, scrn,0);    /* BYU 2.4.16 */
  246.         return;                                        /* BYU 2.4.16 */
  247.     }                                                /* BYU 2.4.16 */
  248.     if (screens[scrn].outcount < 2) {                /* BYU 2.4.16 */
  249.         screens[scrn].outcount++;                    /* BYU 2.4.16 */
  250.         netputevent( USERCLASS, PASTELEFT, scrn,0);    /* BYU 2.4.16 */
  251.         return;                                        /* BYU 2.4.16 */
  252.     }
  253.     if (netqlen(screens[scrn].port) > 0) {            /* BYU 2.4.16 - wait until not full */
  254.         netputevent( USERCLASS, PASTELEFT, scrn,0);    /* BYU 2.4.16 */
  255.         return;                                        /* BYU 2.4.16 */
  256.     }                                                /* BYU 2.4.16 */
  257.  
  258.     if (!screens[scrn].pastemethod) {    // Do this all at once?
  259.         amount = netwrite(screens[scrn].port, screens[scrn].outptr,
  260.                             screens[scrn].outlen);
  261.         }
  262.     else {        // Nope, do it in blocks
  263.         if (screens[scrn].pastesize <= screens[scrn].outlen)
  264.             amount = screens[scrn].pastesize;
  265.         else
  266.             amount = screens[scrn].outlen;
  267.         amount = netwrite(screens[scrn].port, screens[scrn].outptr, amount);
  268.         }
  269.         
  270.     if (screens[scrn].echo)    
  271.         parse( &screens[scrn],(unsigned char *) screens[scrn].outptr,amount);
  272.     
  273.     screens[scrn].outlen -= amount;    
  274.     screens[scrn].outptr += (long) amount;
  275.  
  276.     if ( screens[scrn].outlen <=0) {
  277.         int left;
  278.         WindRec *tw = &screens[scrn];
  279.         tw->clientflags &= ~PASTE_IN_PROGRESS;
  280.         HUnlock(tw->outhand);
  281.         DisposHandle(tw->outhand);
  282.         tw->outptr = (char *) 0L;    
  283.         tw->outhand = (char **) 0L;    
  284.         
  285.         //this next loop is to unload the queue of stuff typed during the paste
  286.         for (left = 0; left < tw->kblen; left++) 
  287.         {
  288.             if ((tw->kbbuf[left]) == 0) //this signals a VSkey
  289.             {
  290.                 left++; //send the VS key
  291.                 VSkbsend(tw->vs, (unsigned char) tw->kbbuf[left], tw->echo);
  292.             }
  293.             else
  294.             {
  295.                 netpush(tw->port);
  296.                 if (tw->kbbuf[left+1] != 0x15) //not a KILLCHAR
  297.                 {    
  298.                     if (tw->kbbuf[left] == '\015') // remap CR-> CR LF
  299.                     {
  300.                         netwrite(tw->port,"\015\012",2);
  301.                         if (tw->echo)
  302.                             parse(tw,(unsigned char *) "\012\015",2);
  303.                         return;
  304.                     }
  305.                     netwrite(tw->port,&(tw->kbbuf[left]),1);
  306.                     if (tw->echo && (tw->kbbuf[left]>31) && (tw->kbbuf[left] <127))    
  307.                         parse(tw,(unsigned char *)&(tw->kbbuf[left]),1);
  308.                     else if (tw->echo)
  309.                     {
  310.                         tw->kbbuf[left] += '@';
  311.                         parse(tw,(unsigned char *) "^",1);    /* BYU LSC */
  312.                         parse(tw, (unsigned char *)&(tw->kbbuf[left]), 1);
  313.                     }
  314.                 }
  315.                 else
  316.                     left++; //user cancelled one keystroke with another
  317.             }
  318.         }
  319.     }
  320.     else
  321.         netputevent( USERCLASS, PASTELEFT, scrn,0);
  322. }
  323.  
  324. void DoNetEvents(void)
  325. {
  326.     long    ftptime = 0;
  327.     short    event, class, data1;
  328.     long    data2, pos;
  329.     
  330.     if ((event = netgetevent(&class, &data1, &data2)) < 0) return;
  331.  
  332.     if ( (TickCount() - ftptime > 60*2) && FileInTransit) {
  333.         ftptime = TickCount();
  334.         Sftpstat(&pos);                    /* get transfer status */
  335.         if (pos <= 0) 
  336.             ftpmess("FTP Status: transferring\015\012");
  337.         else 
  338.             {
  339.             char *temp;
  340.             temp = myNewPtr(50);    //enough room for this string
  341.             if (temp == NULL)
  342.                 return;  //Not enough memory to print status
  343.             if (FileInTransit+2)
  344.                 sprintf((char *) temp,"FTP Status: %ld bytes remaining.\015\012", pos);        /* BYU LSC */
  345.             else
  346.                 sprintf((char *) temp,"FTP Status: %ld bytes transferred.\015\012", pos);    /* BYU LSC */
  347.  
  348.             ftpmess((char *) temp);    /* BYU LSC */
  349.             DisposePtr(temp);
  350.             }
  351.         }
  352.         
  353.     switch(class) {
  354.         case SCLASS:
  355.             switch (event) {
  356.                 case FTPACT:
  357.                     ftpd(0, data1);
  358.                     break;
  359.                 case CLOSEDONE:                    /* Used in the drivers */
  360.                     netclose(data1);
  361.                     break;
  362.                 case CLOSEDONE+1:                /* Used in the drivers */
  363.                     netclose(data1);
  364.                     break;
  365.                 default:
  366.                     break;
  367.             }
  368.             break;
  369.             
  370.         case CONCLASS:                            /* Connection type event */
  371.             switch(GetPortType(data1)) {
  372.                 case PFTP:
  373.                     rftpd(event,data1);        /* BYU 2.4.16 */
  374.                     break;
  375.                 case PDATA:
  376.                     ftpd(event,data1);
  377.                     break;
  378.                 default:
  379.                 case CNXN_TYPE:
  380.                     switch (event) {
  381.                         case CONOPEN:                /* connection opened or closed */
  382.                             ConnectionOpenEvent(data1);
  383.                             break;
  384.          
  385.                         case CONDATA:                /* data arrived for me */
  386.                             ConnectionDataEvent(data1);
  387.                             break;
  388.         
  389.                         case CONFAIL:
  390.                             ConnectionFailedEvent(data1);
  391.                             break;
  392.         
  393.                         case CONCLOSE:
  394.                             ConnectionClosedEvent(data1);
  395.                             break;
  396.         
  397.                         default:
  398.                             break;
  399.                         }
  400.                     break;    /* Case port type = CNXN_TYPE */
  401.                 }
  402.             break;    /* CONCLASS */
  403.  
  404.     case USERCLASS:
  405.             switch (event) {
  406.                 case DOMAIN_DONE:    // data1 = screen #, data2 = ptr to info structure
  407.                     HandleDomainDoneMessage(data1, data2);
  408.                     break;
  409.                 case FTPBEGIN:
  410.                     FileInTransit=data1;
  411.                     ftptime=TickCount();
  412.                     break;
  413.                 case FTPEND:
  414.                     ftpmess("FTP Transfer Concluding\015\012");
  415.                     ftpmess("\015\012");
  416.                     FileInTransit=0;
  417.                     break;
  418.                 case FTPCOPEN:
  419.                     {
  420.                         ip_addrbytes    ftpinfo;
  421.                         
  422.                         Str255    remoteMachineName;
  423.                         
  424.                         char *temp;
  425.                         if (gFTPServerPrefs->ResetMacBinary) 
  426.                             TelInfo->MacBinary = gFTPServerPrefs->UseMacBinaryII;
  427.                         updateMenuChecks();
  428.                         TelInfo->xferon=1;
  429.                         updateCursor(1);
  430.                         
  431.                         ftpmess("-----------------------------------------------------------------------------\015\012");
  432.                         ftpmess("FTP server initiated from host: ");
  433.                         temp = myNewPtr(80);
  434.                         ftpinfo.a.addr = Sftphost();
  435.  
  436.                         if (temp != NULL) //enough memory to tell the log about the ftp session
  437.                         {
  438.                             if (!TranslateIPtoDNSname(ftpinfo.a.addr, remoteMachineName)) 
  439.                                 sprintf((char *) &temp[4],"%u.%u.%u.%u\015\012",
  440.                                     (unsigned char)ftpinfo.a.byte[0],
  441.                                     (unsigned char)ftpinfo.a.byte[1],
  442.                                     (unsigned char)ftpinfo.a.byte[2],
  443.                                     (unsigned char)ftpinfo.a.byte[3]);
  444.                             else 
  445.                             {
  446.                                 PtoCstr(remoteMachineName);
  447.                                 sprintf((char *) &temp[4],"%s\015\012",remoteMachineName);
  448.                             }
  449.                         ftpmess((char *) &temp[4]);        /* BYU LSC */
  450.                         DisposePtr(temp);
  451.                         }
  452.                     }
  453.                     break;
  454.                 case FTPCLOSE:
  455.                     TelInfo->xferon=0;
  456.                     updateCursor(1);
  457.                     if (gFTPServerPrefs->ResetMacBinary) 
  458.                         TelInfo->MacBinary = gFTPServerPrefs->UseMacBinaryII;
  459.                     updateMenuChecks();
  460.                     ftpmess("FTP server ending session\015\012");
  461.                     ftpmess("-----------------------------------------------------------------------------\015\012");
  462.                     ftpmess("\015\012");
  463.  
  464.                     break;
  465.                 case RG_REDRAW:            /* RGredraw event */
  466.                     if (VGalive(data1) && RGsupdate(data1))
  467.                         TekEnable(data1);
  468.                     break;
  469.                 case PASTELEFT:
  470.                     pasteText(data1);
  471.                     break;
  472.                 default:
  473.                     break;
  474.             }
  475.             break;    /* USERCLASS */
  476.  
  477.     default:
  478.         break;
  479.     } /* switch (CLASS) */
  480.     
  481. } /* DoNetEvents */
  482.         
  483. /*    setblocksize()
  484.         Make sure that we have space for the block of data that is to be read each
  485.         time the netread() is called.
  486.         
  487.         2.7: Different gBlockSize for each scrn, same gReadSpace  -- CCP */
  488.         
  489. short setReadBlockSize(short tosize, short scrn)
  490. {
  491.     short currentSize;
  492.     gBlocksize[scrn] = tosize;                            /* keep size of block */
  493.  
  494.     if (tosize < 512)                            /* minimum buffer */
  495.         gBlocksize[scrn] = 512;
  496.     
  497.     if (gReadspace == NULL)
  498.     {
  499.         gReadspace = (unsigned char *) myNewPtrCritical(tosize+100); 
  500.         if (gReadspace == NULL)
  501.             return -1;    //ick--lets handle this better
  502.     }
  503.     else
  504.     {
  505.         currentSize = (short) GetPtrSize((Ptr)gReadspace);
  506.     
  507.         if (currentSize < (tosize+100))    //increase buffer size, if possible
  508.         {
  509.             DisposePtr((Ptr)gReadspace);
  510.             gReadspace = (unsigned char *)myNewPtrCritical(tosize + 100);
  511.             if (gReadspace == NULL)
  512.             {
  513.                 if  (NULL == (gReadspace = (unsigned char *)myNewPtrCritical(currentSize))) //try to get old size
  514.                     return(-1);                //ick--lets handle this better
  515.                 gBlocksize[scrn] = currentSize;
  516.             }
  517.         }
  518.     }
  519.     return(0);
  520.  
  521. }
  522.